/*
 * @Author: dgflash
 * @Date: 2022-04-14 17:08:01
 * @LastEditors: dgflash
 * @LastEditTime: 2023-08-11 10:00:51
 */
import { _decorator } from "cc";
import LabelNumber from "./LabelNumber";

const { ccclass, property, menu } = _decorator;

/** 数值变化动画标签组件 */
@ccclass("LabelChange")
@menu('OopsFramework/Label/LabelChange （数值变化动画标签）')
export class LabelChange extends LabelNumber {
    @property
    isInteger: boolean = false;

    private duration: number = 0;            // 持续时间
    private callback: Function | undefined;  // 完成回调
    private isBegin: boolean = false;        // 是否开始
    private speed: number = 0;               // 变化速度
    private end: number = 0;                 // 最终值
    private remainingCallbacks: Function[] = []; // 存储待执行的回调函数

    /**
     * 变化到某值,如果从当前开始的begin传入null
     * @param {number} duration 
     * @param {number} end 
     * @param {Function} [callback]
     */
    public changeTo(duration: number, end: number, callback?: Function) {
        if (duration == 0) {
            if (callback) callback();
            if (duration == 0) {
                this.num = end;
            }
            return;
        }
        
        // 如果当前正在执行动画，直接修改目标值
        if (this.isBegin) {
            // 保存原来的回调
            if (this.callback) {
                this.remainingCallbacks.push(this.callback);
            }
            
            // 更新目标值和速度
            const begin = this.num;
            this.duration = duration;
            this.end = end;
            this.callback = callback;
            this.speed = (end - begin) / duration;
        } else {
            this.playAnim(duration, this.num, end, callback);
        }
    }


    /**
     * 变化值,如果从当前开始的begin传入null
     * @param {number} duration 
     * @param {number} value 
     * @param {Function} [callback] 
     * @memberof LabelChange
     */
    public changeBy(duration: number, value: number, callback?: Function) {
        if (duration == 0 || value == 0) {
            if (callback) callback();
            if (duration == 0) {
                this.num = this.num + value;
            }
            return;
        }
        
        // 如果当前正在执行动画，累加到目标值上
        if (this.isBegin) {
            // 保存原来的回调
            if (this.callback) {
                this.remainingCallbacks.push(this.callback);
            }
            
            // 更新目标值和速度
            const begin = this.num;
            const newEnd = this.end + value; // 累加到原目标值上
            this.duration = duration;
            this.end = newEnd;
            this.callback = callback;
            this.speed = (newEnd - begin) / duration;
        } else {
            this.playAnim(duration, this.num, this.num + value, callback);
        }
    }

    /** 立刻停止 */
    public stop(excCallback: boolean = true) {
        this.num = this.end;
        this.isBegin = false;
        
        // 执行所有回调
        if (excCallback) {
            // 先执行当前回调
            if (this.callback) this.callback();
            
            // 再执行剩余的回调
            while (this.remainingCallbacks.length > 0) {
                const cb = this.remainingCallbacks.shift();
                if (cb) cb();
            }
        } else {
            // 清空回调队列
            this.remainingCallbacks = [];
        }
        
        this.callback = undefined;
    }

    /** 播放动画 */
    private playAnim(duration: number, begin: number, end: number, callback?: Function) {
        this.duration = duration;
        this.end = end;
        this.callback = callback;
        this.speed = (end - begin) / duration;
        this.remainingCallbacks = []; // 清空回调队列

        this.num = begin;
        this.isBegin = true;
    }

    /** 是否已经结束 */
    private isEnd(num: number): boolean {
        if (this.speed > 0) {
            return num >= this.end;
        }
        else {
            return num <= this.end;
        }
    }

    update(dt: number) {
        if (this.isBegin) {
            if (this.num == this.end) {
                this.isBegin = false;
                
                // 执行当前回调
                const currentCallback = this.callback;
                this.callback = undefined;
                
                if (currentCallback) currentCallback();
                
                // 执行剩余的回调
                while (this.remainingCallbacks.length > 0) {
                    const cb = this.remainingCallbacks.shift();
                    if (cb) cb();
                }
                
                return;
            }
            let num = this.num + dt * this.speed;

            if (this.isInteger){
                if(this.end < this.num)
                {
                    num = Math.floor(num);
                }
                else{
                    num = Math.ceil(num);
                }
            }

            /** 变化完成 */
            if (this.isEnd(num)) {
                num = this.end;
                this.isBegin = false;
                
                // 执行当前回调
                const currentCallback = this.callback;
                this.callback = undefined;
                
                if (currentCallback) currentCallback();
                
                // 执行剩余的回调
                while (this.remainingCallbacks.length > 0) {
                    const cb = this.remainingCallbacks.shift();
                    if (cb) cb();
                }
            }
            this.num = num;
        }
    }
}